//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "Utils/UI/UIFrame.h"
#include "Utils/UI/UILocale.h"
#include "Utils/UI/UILocalization.h"

namespace Engine
{
namespace Utils
{


	//
	// UI Config Loader
	//

	class UIConfigLoader
	{
	// variables
	private:
		Ptr< UtilsCore >	_core;
		UIAllLocalizations	_locs;


	// methods
	public:
		UIConfigLoader (UtilsCore *core) : _core(core), _locs(core)
		{
			InitMetaData();
		}

		~UIConfigLoader ()
		{}

		bool LoadConfig (uni_c_string filename, uni_c_string outputPath, bool clearOutputDir);
		bool LoadFrame (uni_c_string filename, UIFrame &frame);
		bool LoadLocales (uni_c_string path);

		bool SaveFrame (uni_c_string filename, UIFrame &frame);
		bool SaveLocale (uni_c_string filename);


	// metadata
	public:
		typedef UILocalization::LocalePack	LocalePack;

		struct FrameList
		{
			string_array_t		frames;
			string_array_t		directories;
			string				outputDir;
			string				inputDir;
			string				extension;
			
			string				localeInputDir;
			string				localeOutputDir;
			string				localeSettings;
			string				localeExtension;
			string				localeSettingsExt;
			string				localeDefault;
			array< LocalePack >	localeOutputPacks;
		};


		static CMetaClass &	MetaFrameList ()		{ static CMetaClass metaClass;	return metaClass; }
		static CMetaClass &	MetaLocalePack ()		{ static CMetaClass	metaClass;	return metaClass; }

		static void InitMetaData ();
	};

	


	// LoadConfig
	inline bool UIConfigLoader::LoadConfig (uni_c_string filename, uni_c_string outputPath, bool clearOutputDir)
	{
		static_obj_tree_t	cfg_tree;

		FrameList			frame_list;

		cfg_tree.Push( TConfigObjInfo( MetaFrameList().GetSetIter( frame_list ), null ) );
		
		const string	input_path = FileAddressUtils::GetPath( filename );

		_core->Config()->ClearDerectories();
		_core->Config()->AddDirectory( input_path );
		_core->Config()->AddDirectory( "" );

		CHECK_ERR( _core->Parse( filename, cfg_tree ) );

		string	input_dir;
		string	output_dir;

		FileAddressUtils::BuildPath( input_dir, input_path, frame_list.inputDir );
		FileAddressUtils::BuildPath( output_dir, outputPath, frame_list.outputDir );
		
		// create output dir
		if ( not FileSystem::IsDirectoryExist( output_dir.cstr() ) )
		{
			FileSystem::NewDirectory( output_dir.cstr() );
		}

		if ( clearOutputDir )
		{
			_core->ClearDir( output_dir );
		}


		string	loc_input_dir;
		string	loc_output_dir;

		FileAddressUtils::BuildPath( loc_input_dir, input_path, frame_list.localeInputDir );
		FileAddressUtils::BuildPath( loc_output_dir, outputPath, frame_list.localeOutputDir );

		CHECK_ERR( _locs.Load(	loc_input_dir,				frame_list.localeSettings,
									frame_list.localeDefault,	frame_list.localeOutputPacks ) );
		
		if ( not FileSystem::IsDirectoryExist( loc_output_dir.cstr() ) )
		{
			FileSystem::NewDirectory( loc_output_dir.cstr() );
		}

		CHECK_ERR( _locs.Save( loc_output_dir, frame_list.localeExtension, frame_list.localeSettingsExt ) );


		FOR( i, frame_list.directories )
		{
			string	path;
			FileAddressUtils::BuildPath( path, input_path, frame_list.directories[i] );

			_core->Config()->AddDirectory( path );
		}

		FOR( i, frame_list.frames )
		{
			UIFrame	frame;

			string	in_fname;
			FileAddressUtils::BuildPath( in_fname, input_dir, frame_list.frames[i] );

			LoadFrame( in_fname, frame );
			
			string	fname;
			FileAddressUtils::BuildPath( fname, output_dir, frame_list.frames[i], frame_list.extension );

			SaveFrame( fname, frame );
		}

		return true;
	}


	// LoadFrame
	inline bool UIConfigLoader::LoadFrame (uni_c_string filename, UIFrame &frame)
	{
		static_obj_tree_t	cfg_tree;

		cfg_tree.Push( TConfigObjInfo( frame.GetMetaIterator(), null ) );

		CHECK_ERR( _core->Parse( filename, cfg_tree ) );

		frame.OnLoad( _locs.GetDefaultLocale() );
		return true;
	}


	// SaveFrame
	inline bool UIConfigLoader::SaveFrame (uni_c_string filename, UIFrame &frame)
	{
		WFilePtr	file;
		CHECK_ERR( (file = File::HddWFile::New( filename )).IsNotNull() );
		
		RESFILE_WRITE_HEADER( file, UIFrameFileInfo );

		frame.Serialize( file );
		return true;
	}


	inline UX_CREATE_META_OBJECT( UIConfigLoader::FrameList,	UIConfigLoader::MetaFrameList()  );
	inline UX_CREATE_META_OBJECT( UIConfigLoader::LocalePack,	UIConfigLoader::MetaLocalePack() );


	// InitMetaData
	inline void UIConfigLoader::InitMetaData ()
	{
		CMetaAddIteratorPtr	iter;

		CMetaClass::s_InitBaseTypes();
			
		UIFrame().InitMetaData();

		if ( not MetaLocalePack().IsInit() )
		{
			LocalePack	obj;

			MetaLocalePack().CreateExt( "UILocalePack", obj );
			iter = MetaLocalePack().GetAddIter( obj );

			iter->AddField( obj.files,	"files"	);
			iter->AddField( obj.id,		"id"	);
			iter->AddField( obj.name,	"name"	);
		}

		if ( not MetaFrameList().IsInit() )
		{
			FrameList	obj;

			MetaFrameList().CreateExt( "UIConfig", obj );
			iter = MetaFrameList().GetAddIter( obj );

			iter->AddField( obj.frames,				"frames" );
			iter->AddField( obj.directories,		"directories" );
			iter->AddField( obj.outputDir,			"output_dir" );
			iter->AddField( obj.inputDir,			"input_dir" );
			iter->AddField( obj.extension,			"extension" );

			iter->AddField( obj.localeExtension,	"locale_extension" );
			iter->AddField( obj.localeInputDir,		"locale_input_dir" );
			iter->AddField( obj.localeOutputDir,	"locale_output_dir" );
			iter->AddField( obj.localeSettings,		"locale_settings" );
			iter->AddField( obj.localeSettingsExt,	"locale_settings_ext" );
			iter->AddField( obj.localeDefault,		"locale_default" );
			iter->AddField( obj.localeOutputPacks,	"locale_output_packs" );
		}
	}



}	// Utils
}	// Engine